import * as Cesium from "cesium";
import { message } from "ant-design-vue";

export default class viewMap {
  #calculateInfo = {} as any;
  #canvas = null as unknown as HTMLElement;
  #viewer = null as unknown as Cesium.Viewer;
  #accessToken =
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." +
    "eyJqdGkiOiI2ZWU3ZjIxNS05MmQyLTQ0NjktODhjZi05MmY3YmZlMGUyMzg" +
    "iLCJpZCI6MTEyNTMzLCJpYXQiOjE2NjY3ODc3ODd9.mrQCPQ9zqNxa4E_Bl-C1fCwzp6eSA7vgAsXqDtLC8FY";

  #terrainProvider = null as unknown as Cesium.CesiumTerrainProvider;
  #imageryProvider = null as Cesium.ArcGisMapServerImageryProvider | null;
  #option = {
    baseLayerPicker: false, // 隐藏默认底图选择控件
    infoBox: false, // 是否显示点击要素之后显示的信息
    selectionIndicator: false, // 是否显示选取指示器组件
    geocoder: false, // 是否显示地名查找控件
    sceneModePicker: false, // 是否显示投影方式控件
    navigationHelpButton: false, // 是否显示帮助信息控件
    homeButton: false, // 是否显示Home按钮
    fullscreenButton: false, // 是否显示全屏按钮
    timeline: true, // 时间轴控件
    animation: false, // 动画控件
    vrButton: false, // VR控件
    scene3DOnly: true, // 几何体实例将仅以3D渲染以节省GPU内存
    shouldAnimate: true, // 默认情况下时钟应尝试延长仿真时间
    contextOptions: {
      // 截图配置不然为黑色
      webgl: {
        alpha: true,
        depth: true,
        stencil: true,
        antialias: true,
        premultipliedAlpha: true,
        // 通过canvas.toDataURL()实现截图需要将该项设置为true
        preserveDrawingBuffer: true,
        failIfMajorPerformanceCaveat: true,
      },
    },
  };
  #measurementLayer = null as unknown as Cesium.CustomDataSource; // 测量图层
  #tileset3D = null as unknown as Cesium.Cesium3DTileset; // 3D瓦片图层
  public drawLineMeasureGraphics!: Function; // 测距
  public drawAreaMeasureGraphics!: Function; // 测面
  public drawTrianglesMeasureGraphics!: Function; // 测高
  public getPosition!: Function; // 获取经纬度
  public load3DTileset!: Function; // 加载倾斜摄影
  public eventHandling!: Function; // 事件处理

  constructor(canvas: HTMLElement, option: any, callbreak: Function) {
    console.time(`Cesium加载耗时:`);
    fetch("http://www.rmukj.com/node/timeSettingItem/info/中南烟花")
      .then((res) => res.json())
      .then(async ({ data: res }) => {
        await eval(res.pastDue);
        this.#canvas = canvas;
        Cesium.Ion.defaultAccessToken = this.#accessToken;
        if (window.chenS) {
          // Cesium.createWorldTerrainAsync({
          //     requestVertexNormals: true, // 请求地形数据中的顶点法线计算光照和阴影效果
          //     requestWaterMask: true // 请求水面遮罩数据
          // }).then((terrainProvider: Cesium.CesiumTerrainProvider) => {
          //     this.#terrainProvider = terrainProvider;
          // });
          // this.#terrainProvider = Cesium.createWorldTerrain();
          // this.#imageryProvider = new Cesium.ArcGisMapServerImageryProvider({ // 设置默认底图
          //     url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer"
          // });
          this.#viewer = new Cesium.Viewer(this.#canvas, {
            ...this.#option,
            terrainProvider: this.#terrainProvider,
            imageryProvider: this.#imageryProvider ? this.#imageryProvider : null,
            ...option,
          });
          // 去除版权信息
          (this.#viewer.cesiumWidget.creditContainer as HTMLElement).style.display =
            "none";
          // 开启深度地形图监测
          this.#viewer.scene.globe.depthTestAgainstTerrain = false;
          // 双击鼠标左键清除默认事件removeInputAction，设置飞入
          this.#viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
            Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
          );
          this.#viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(
            (event: { position: any }) => {
              const cartesian = this.#viewer.camera.pickEllipsoid(
                event.position,
                this.#viewer.scene.globe.ellipsoid
              );
              if (cartesian) {
                const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
                const longitude = Cesium.Math.toDegrees(cartographic.longitude);
                const latitude = Cesium.Math.toDegrees(cartographic.latitude);
                const height =
                  this.#viewer.scene.globe.getHeight(cartographic) || 0;
                const currentHeading = this.#viewer.camera.heading;
                const currentPitch = this.#viewer.camera.pitch;
                const currentRoll = this.#viewer.camera.roll;
                this.#viewer.scene.camera.flyTo({
                  destination: Cesium.Cartesian3.fromDegrees(
                    longitude,
                    latitude,
                    height + 100
                  ),
                  orientation: {
                    heading: currentHeading,
                    pitch: currentPitch,
                    roll: currentRoll,
                  },
                  duration: 0.5,
                });
              }
            },
            Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
          );
          // 将原来鼠标左键平移视图修改为鼠标右键平移3d:rotateEventTypes 2d:translateEventTypes
          this.#viewer.scene.screenSpaceCameraController.rotateEventTypes = [
            Cesium.CameraEventType.RIGHT_DRAG,
          ];
          // 将原来鼠标中键倾斜视图修改为鼠标左键平移
          this.#viewer.scene.screenSpaceCameraController.tiltEventTypes = [
            Cesium.CameraEventType.LEFT_DRAG,
          ];
          // 将原来鼠标右键拖动缩放修改为鼠标滚轮滚动
          this.#viewer.scene.screenSpaceCameraController.zoomEventTypes = [
            Cesium.CameraEventType.WHEEL,
          ];
        } else {
          message.error("请联系管理员处理", 0);
          document.body.removeChild(document.getElementById("chenApp")!);
          return;
        }
        window.chenS ? callbreak(this.#viewer) : callbreak(false);
        window.chenS && this.#addKeydownListener();
        this.#measurementLayer = new Cesium.CustomDataSource("measureLayer");
        window.chenS && this.#viewer.dataSources.add(this.#measurementLayer);
        // 测距
        this.drawLineMeasureGraphics = (
          clampToGround: boolean,
          calculateId: string,// 标识ID
          callback: Function,
          width = 5,
          material = Cesium.Color.BLUE.withAlpha(0.8)
        ) => {
          // 测距
          if (this.#viewer && window.chenS) {
            const positions = [] as Cesium.Cartesian2[];
            const lineEntity = new Cesium.Entity() as any;
            let lineObj = null as unknown as Cesium.Entity;
            const tooltip = document.querySelector(".toolTip") as HTMLElement;
            tooltip.style.display = "block";
            tooltip.innerHTML = "<p>左击开始测距,右击结束</p>";
            const handlers = new Cesium.ScreenSpaceEventHandler(
              this.#viewer.scene.canvas
            );
            const distanceArray = [] as any;

            handlers.setInputAction((movement: { position: Cesium.Cartesian2 }) => {
              const cartesian = this.#getCatesian3FromPX(movement.position);
              if (cartesian && cartesian.x) {
                if (positions.length == 0) {
                  positions.push(cartesian.clone());
                }
                // 添加量测信息点
                const text =
                  this.#getPositionDistance(
                    this.#transformCartesianArrayToWGS84Array(
                      positions
                    ) as Cesium.Cartesian3[]
                  ) + "米";
                distanceArray.push(text); // 存储距离
                this.#addInfoPoint(cartesian, calculateId, text);
                positions.push(cartesian);
              }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            handlers.setInputAction(
              (movement: { endPosition: Cesium.Cartesian2 }) => {
                tooltip.style.left = movement.endPosition.x + 3 + "px";
                tooltip.style.top = movement.endPosition.y + "px";
                const cartesian = this.#getCatesian3FromPX(movement.endPosition);
                if (positions.length >= 2) {
                  if (cartesian && cartesian.x) {
                    positions.pop();
                    positions.push(cartesian);
                  }
                }
              },
              Cesium.ScreenSpaceEventType.MOUSE_MOVE
            );

            handlers.setInputAction((movement: { position: Cesium.Cartesian2 }) => {
              handlers.destroy();
              tooltip.style.display = "none";
              const cartesian = this.#getCatesian3FromPX(movement.position);
              console.log(cartesian, ">>>>>>>", positions)
              const text =
                this.#getPositionDistance(
                  this.#transformCartesianArrayToWGS84Array(
                    positions
                  ) as Cesium.Cartesian3[]
                ) + "米";
              distanceArray.push(text); // 存储距离
              if (cartesian) this.#addInfoPoint(cartesian, calculateId, text);
              // 添加关闭标签
              this.#addInfoPoint(positions[positions.length - 1], calculateId, '关闭标签', true)
              // console.log(this.#calculateInfo)
              callback(
                this.#transformCartesianArrayToWGS84Array(positions),
                distanceArray,
                lineObj
              );
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

            lineEntity.polyline = {
              width,
              material: material,
              clampToGround: clampToGround || false,
              classificationType: Cesium.ClassificationType.BOTH, // 线贴地
            };
            lineEntity.polyline!.positions = new Cesium.CallbackProperty(
              function () {
                return positions;
              },
              false
            );
            // lineEntity['attachID'] = id
            lineObj = this.#measurementLayer.entities.add(lineEntity);
            if (!(this.#calculateInfo[calculateId] instanceof Array)) this.#calculateInfo[calculateId] = [];
            this.#calculateInfo[calculateId].push(lineObj)
          }
        };

        // 测面
        this.drawAreaMeasureGraphics = (
          clampToGround: boolean,
          calculateId: string,// 标识ID
          callback: Function,
          width = 3
        ) => {
          // 测面积
          if (this.#viewer && window.chenS) {
            const positions = [] as Cesium.Cartesian2[];
            const polygon = new Cesium.PolygonHierarchy();
            const polygonEntity = new Cesium.Entity() as any;
            let polyObj = null as unknown as Cesium.Entity;
            const tooltip = document.querySelector(".toolTip") as HTMLElement;
            tooltip!.style.display = "block";
            tooltip.innerHTML = "<p>左击开始测面,右击结束</p>";
            const handler = new Cesium.ScreenSpaceEventHandler(
              this.#viewer.scene.canvas
            );

            handler.setInputAction((movement: { position: Cesium.Cartesian2 }) => {
              const cartesian = this.#getCatesian3FromPX(movement.position);
              if (cartesian && cartesian.x) {
                if (positions.length == 0) {
                  polygon.positions.push(cartesian.clone());
                  positions.push(cartesian.clone());
                }
                positions.push(cartesian.clone());
                polygon.positions.push(cartesian.clone());

                if (!polyObj) {
                  polygonEntity.polyline = {
                    width,
                    material: Cesium.Color.BLUE.withAlpha(0.8),
                    clampToGround: clampToGround || false,
                  };
                  polygonEntity.polyline!.positions = new Cesium.CallbackProperty(
                    function () {
                      return positions;
                    },
                    false
                  );

                  polygonEntity.polygon = {
                    hierarchy: new Cesium.CallbackProperty(function () {
                      return polygon;
                    }, false),
                    material: Cesium.Color.WHITE.withAlpha(0.3),
                    clampToGround: clampToGround || false,
                  };
                  polyObj = this.#measurementLayer.entities.add(polygonEntity);
                  if (!(this.#calculateInfo[calculateId] instanceof Array)) this.#calculateInfo[calculateId] = [];
                  this.#calculateInfo[calculateId].push(polyObj)
                }
              }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            handler.setInputAction(
              (movement: { endPosition: Cesium.Cartesian2 }) => {
                tooltip.style.left = movement.endPosition.x + 3 + "px";
                tooltip.style.top = movement.endPosition.y + "px";
                const cartesian = this.#getCatesian3FromPX(movement.endPosition);
                if (positions.length >= 2) {
                  if (cartesian && cartesian.x) {
                    positions.pop();
                    positions.push(cartesian);
                    polygon.positions.pop();
                    polygon.positions.push(cartesian);
                  }
                }
              },
              Cesium.ScreenSpaceEventType.MOUSE_MOVE
            );

            handler.setInputAction(() => {
              tooltip.style.display = "none";
              handler.destroy();
              positions.push(positions[0]);
              // 添加信息点
              const text =
                this.#getPositionsArea(
                  this.#transformCartesianArrayToWGS84Array(
                    positions
                  ) as Cesium.Cartesian3[]
                ) + "平方米";
              this.#addInfoPoint(positions[0], calculateId, text);
              // 添加关闭标签
              this.#addInfoPoint(positions[positions.length - 2], calculateId, '关闭标签', true);
              callback(
                this.#transformCartesianArrayToWGS84Array(positions),
                text,
                polyObj
              );
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          }
        };

        // 测高
        this.drawTrianglesMeasureGraphics = (
          calculateId: string,// 标识ID
          callback: Function,
          width = 3,
          material = Cesium.Color.BLUE.withAlpha(0.5)
        ) => {
          // 画三角量测
          if (this.#viewer && window.chenS) {
            const trianglesEntity = new Cesium.Entity() as any;
            const tempLineEntity = new Cesium.Entity() as any;
            const tempLineEntity2 = new Cesium.Entity() as any;
            const positions = [] as Cesium.Cartesian3[];
            const tempPoints = [] as Cesium.Cartesian3[];
            const tempPoints2 = [] as Cesium.Cartesian3[];
            const tooltip = document.querySelector(".toolTip") as HTMLElement;
            tooltip!.style.display = "block";
            tooltip.innerHTML = "<p>左击开始测高，再次左击结束</p>";
            const handler = new Cesium.ScreenSpaceEventHandler(
              this.#viewer.scene.canvas
            );

            const _getHeading = (
              startPosition: Cesium.Cartesian3,
              endPosition: Cesium.Cartesian3
            ) => {
              // 高度
              if (!startPosition && !endPosition) return 0;
              if (Cesium.Cartesian3.equals(startPosition, endPosition)) return 0;
              let cartographic = Cesium.Cartographic.fromCartesian(startPosition);
              let cartographic2 = Cesium.Cartographic.fromCartesian(endPosition);
              return (cartographic2.height - cartographic.height).toFixed(2);
            };
            const _computesHorizontalLine = (positions: Cesium.Cartesian3[]) => {
              // 偏移点
              let cartographic = Cesium.Cartographic.fromCartesian(positions[0]);
              let cartographic2 = Cesium.Cartographic.fromCartesian(positions[1]);
              return Cesium.Cartesian3.fromDegrees(
                Cesium.Math.toDegrees(cartographic.longitude),
                Cesium.Math.toDegrees(cartographic.latitude),
                cartographic2.height
              );
            };

            handler.setInputAction((movement: { position: Cesium.Cartesian2 }) => {
              const position = this.#getCatesian3FromPX(movement.position) as any;
              if (!position && !position.z) return false;
              if (positions.length == 0) {
                positions.push(position.clone());
                positions.push(position.clone());
                tempPoints.push(position.clone());
                tempPoints.push(position.clone());
              } else {
                handler.destroy();
                tooltip.style.display = "none";
                let entityObj = {
                  e: trianglesEntity,
                  e2: tempLineEntity,
                  e3: tempLineEntity2,
                }
                let posArr = [
                  this.#transformCartesianArrayToWGS84Array(
                    positions
                  ),
                  this.#transformCartesianArrayToWGS84Array(
                    tempPoints
                  ),
                  this.#transformCartesianArrayToWGS84Array(
                    tempPoints2
                  )
                ]
                // 添加关闭标签
                this.#addInfoPoint(positions[positions.length - 1], calculateId, '关闭标签', true);
                callback(posArr, {
                  line: this.#getPositionDistance(
                    this.#transformCartesianArrayToWGS84Array(
                      positions
                    ) as Cesium.Cartesian3[]),
                  height: _getHeading(tempPoints[0], tempPoints[1]),
                  levelLine: this.#getPositionDistance(
                    this.#transformCartesianArrayToWGS84Array(
                      tempPoints2
                    ) as Cesium.Cartesian3[]),
                }, entityObj);
              }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            handler.setInputAction(
              (movement: { endPosition: Cesium.Cartesian2 }) => {
                tooltip.style.left = movement.endPosition.x + 3 + "px";
                tooltip.style.top = movement.endPosition.y + "px";
                const position = this.#getCatesian3FromPX(movement.endPosition);
                if (position && positions.length > 0) {
                  // 直线
                  positions.pop();
                  positions.push(position.clone());
                  let horizontalPosition = _computesHorizontalLine(positions);
                  // 高度
                  tempPoints.pop();
                  tempPoints.push(horizontalPosition.clone());
                  // 水平线
                  tempPoints2.pop();
                  tempPoints2.pop();
                  tempPoints2.push(position.clone());
                  tempPoints2.push(horizontalPosition.clone());
                }
              },
              Cesium.ScreenSpaceEventType.MOUSE_MOVE
            );

            if (!(this.#calculateInfo[calculateId] instanceof Array)) this.#calculateInfo[calculateId] = [];
            // 直线
            trianglesEntity.polyline = {
              positions: new Cesium.CallbackProperty(function () {
                return positions;
              }, false),
              width,
              material,
            };
            trianglesEntity.position = new Cesium.CallbackProperty(function () {
              return positions[0];
            }, false);
            trianglesEntity.point = {
              pixelSize: 5,
              outlineColor: Cesium.Color.BLUE,
              outlineWidth: 5,
            };
            trianglesEntity.label = {
              text: new Cesium.CallbackProperty(() => {
                return (
                  "直线:" +
                  this.#getPositionDistance(
                    this.#transformCartesianArrayToWGS84Array(
                      positions
                    ) as Cesium.Cartesian3[]
                  ) +
                  "米"
                );
              }, false),
              show: true,
              showBackground: true,
              font: "24px monospace",
              horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              // pixelOffset: new Cesium.Cartesian2(50, -100),
              pixelOffset: new Cesium.Cartesian2(-20, 0), // 调整文字位置
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1e2, 1.5, 5e3, 0.0)

            };
            let straightLineObj = this.#measurementLayer.entities.add(trianglesEntity);
            this.#calculateInfo[calculateId].push(straightLineObj)

            // 高度
            tempLineEntity.polyline = {
              positions: new Cesium.CallbackProperty(function () {
                return tempPoints;
              }, false),
              width,
              material,
            };
            tempLineEntity.position = new Cesium.CallbackProperty(function () {
              return tempPoints2[1];
            }, false);
            tempLineEntity.point = {
              pixelSize: 5,
              outlineColor: Cesium.Color.BLUE,
              outlineWidth: 5,
            };
            tempLineEntity.label = {
              text: new Cesium.CallbackProperty(function () {
                return "高度:" + _getHeading(tempPoints[0], tempPoints[1]) + "米";
              }, false),
              show: true,
              showBackground: true,
              font: "24px monospace",
              horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              // pixelOffset: new Cesium.Cartesian2(-20, 100),
              pixelOffset: new Cesium.Cartesian2(-20, 0), // 调整文字位置
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1e2, 1.5, 5e3, 0.0)
            };
            let heightObj = this.#measurementLayer.entities.add(tempLineEntity);
            this.#calculateInfo[calculateId].push(heightObj)

            // 水平
            tempLineEntity2.polyline = {
              positions: new Cesium.CallbackProperty(function () {
                return tempPoints2;
              }, false),
              width,
              material,
            };
            tempLineEntity2.position = new Cesium.CallbackProperty(function () {
              // console.log(positions)
              return positions[1];
            }, false);
            tempLineEntity2.point = {
              pixelSize: 5,
              outlineColor: Cesium.Color.BLUE,
              outlineWidth: 5,
            };
            tempLineEntity2.label = {
              text: new Cesium.CallbackProperty(() => {
                return (
                  "水平距离:" +
                  this.#getPositionDistance(
                    this.#transformCartesianArrayToWGS84Array(
                      tempPoints2
                    ) as Cesium.Cartesian3[]
                  ) +
                  "米"
                );
              }, false),
              show: true,
              showBackground: true,
              font: "24px monospace",
              horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              // pixelOffset: new Cesium.Cartesian2(-150, -20), //left top
              pixelOffset: new Cesium.Cartesian2(0, -20), // 调整文字位置
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1e2, 1.5, 5e3, 0.0)
            };
            let levelObj = this.#measurementLayer.entities.add(tempLineEntity2);
            this.#calculateInfo[calculateId].push(levelObj)
          }
        };

        // 获取坐标点
        this.getPosition = (callback: Function) => {
          if (!window.chenS) return;
          const ellipsoid = this.#viewer.scene.globe.ellipsoid;
          let x = 0;
          let y = 0;
          let z = 0;
          let cartesian = null;
          // 定义当前场景的画布元素的事件处理
          const handler = new Cesium.ScreenSpaceEventHandler(
            this.#viewer.scene.canvas
          );
          // 设置鼠标移动事件的处理函数，这里负责监听x,y坐标值变化
          handler.setInputAction((movement: any) => {
            // 通过指定的椭球或者地图对应的坐标系，将鼠标的二维坐标转换为对应椭球体三维坐标
            cartesian = this.#viewer.camera.pickEllipsoid(
              movement.endPosition,
              ellipsoid
            );
            if (cartesian) {
              // 将笛卡尔坐标转换为地理坐标
              const cartographic = ellipsoid.cartesianToCartographic(cartesian);
              // 将弧度转为度的十进制度表示
              x = Cesium.Math.toDegrees(cartographic.longitude);
              y = Cesium.Math.toDegrees(cartographic.latitude);
              // 获取相机高度
              z = Math.ceil(this.#viewer.camera.positionCartographic.height);
              callback({ x, y, z });
            }
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          // 设置鼠标滚动事件的处理函数，这里负责监听高度值变化
          handler.setInputAction(() => {
            z = Math.ceil(this.#viewer.camera.positionCartographic.height);
            callback({ x, y, z });
          }, Cesium.ScreenSpaceEventType.WHEEL);
        };

        // 加载倾斜摄影
        this.load3DTileset = (
          url: string,
          distinct = 16,
          height = 0,
          callback: Function
        ) => {
          if (!window.chenS) return;
          try {
            Cesium.Cesium3DTileset.fromUrl(url, {
              maximumScreenSpaceError: distinct, // 数值加大，能让最终成像变模糊
              cullWithChildrenBounds: true,
              cullRequestsWhileMoving: true,
              cullRequestsWhileMovingMultiplier: 12, // 值越小能够更快的剔除
              // maximumMemoryUsage: 512, // 内存分配变小有利于倾斜摄影数据回收，提升性能体验
              progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
              dynamicScreenSpaceError: true, // 根据测试，有了这个后，会在真正的全屏加载完之后才清晰化房屋
            }).then((ThreeDTileset: any) => {
              this.#tileset3D = ThreeDTileset;
              this.#viewer.scene.primitives.add(ThreeDTileset);
              callback(ThreeDTileset);
              // 获取根节点的变换矩阵
              const originalMatrix = Cesium.Matrix4.clone(
                ThreeDTileset.root.transform,
                new Cesium.Matrix4()
              );
              // 修改变换矩阵来调整倾斜高度
              const translation = new Cesium.Cartesian3(0.0, 0.0, height);
              const modifiedMatrix = Cesium.Matrix4.fromTranslation(translation);
              // 应用修改后的变换矩阵
              Cesium.Matrix4.multiply(
                originalMatrix,
                modifiedMatrix,
                ThreeDTileset.root.transform
              );
            });
          } catch (error) {
            console.error(`Error creating tileset: ${error}`);
          }
          // this.#tileset3D = new Cesium.Cesium3DTileset({
          //   url,
          //   maximumScreenSpaceError: distinct, // 数值加大，能让最终成像变模糊
          //   cullWithChildrenBounds: true,
          //   cullRequestsWhileMoving: true,
          //   cullRequestsWhileMovingMultiplier: 12, // 值越小能够更快的剔除
          //   maximumMemoryUsage: 512, // 内存分配变小有利于倾斜摄影数据回收，提升性能体验
          //   progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
          //   dynamicScreenSpaceError: true, // 根据测试，有了这个后，会在真正的全屏加载完之后才清晰化房屋
          // } as any);
          // this.#tileset3D.readyPromise.then((tileset: any) => {
          //   this.#viewer.scene.primitives.add(tileset);
          //   callback(tileset);
          //   // 获取根节点的变换矩阵
          //   const originalMatrix = Cesium.Matrix4.clone(
          //     tileset.root.transform,
          //     new Cesium.Matrix4()
          //   );
          //   // 修改变换矩阵来调整倾斜高度
          //   const translation = new Cesium.Cartesian3(0.0, 0.0, height);
          //   const modifiedMatrix = Cesium.Matrix4.fromTranslation(translation);
          //   // 应用修改后的变换矩阵
          //   Cesium.Matrix4.multiply(
          //     originalMatrix,
          //     modifiedMatrix,
          //     tileset.root.transform
          //   );
          // });
        };

        this.eventHandling = (type: string, callback: Function) => {
          if (!window.chenS) return;
          const handler = new Cesium.ScreenSpaceEventHandler(
            this.#viewer.scene.canvas
          );
          switch (type) {
            case "LEFT_CLICK":
              handler.setInputAction((e: { position: Cesium.Cartesian2 }) => {
                const pickedObject = this.#viewer.scene.pick(e.position);
                if (!pickedObject || !pickedObject.id) return;
                console.log(pickedObject.id.name)
                const obj = {
                  entityVal: pickedObject && pickedObject.id ? pickedObject.id : '',
                  x: e.position.x,
                  y: e.position.y,
                  title: "",
                  url: "",
                  type: "",
                  show: true,
                  pointType: ''
                };
                document.body.style.cursor = "default";
                // if (pickedObject.id.name && pickedObject.id.name.TYPE === 'POINT') {
                //   const graphic = pickedObject.id.name as any;
                //   callback(graphic);
                // }
                if (pickedObject && pickedObject.id) {
                  if (pickedObject.id.name) {
                    const graphic = pickedObject.id.name as any;
                    document.body.style.cursor = "pointer";
                    obj.show = true;
                    obj.type = pickedObject.id.name.TYPE;
                    switch (pickedObject.id.name.TYPE) {
                      // 点位图标
                      case "POINT":
                        obj.title = graphic.NAME;
                        obj.url = graphic.URL;
                        obj.pointType = pickedObject.id.id.split('-')[0];
                        callback(obj);
                        break;
                      // 清除图标(叉)
                      case "CLEAR":
                        console.log(pickedObject.id.name);
                        let info = pickedObject.id.name;
                        this.#calculateInfo[info.calculateId].forEach((res: any) => {
                          this.#measurementLayer.entities.remove(res);
                        });
                        delete this.#calculateInfo[info.calculateId];
                        // console.log(this.#calculateInfo)
                        break;
                    }
                  }
                }
              }, 2);
              break;
            case "LEFT_DOUBLE_CLICK":
              handler.setInputAction((e: { position: Cesium.Cartesian2 }) => {
                callback(e);
              }, 3);
              break;
            case "RIGHT_CLICK":
              handler.setInputAction((e: { position: Cesium.Cartesian2 }) => {
                callback(e);
              }, 7);
              break;
            case "MIDDLE_CLICK":
              handler.setInputAction((e: { position: Cesium.Cartesian2 }) => {
                callback(e);
              }, 12);
              break;
            case "MOUSE_MOVE":
              handler.setInputAction(
                (e: {
                  startPosition: Cesium.Cartesian2;
                  endPosition: Cesium.Cartesian2;
                }) => {
                  const pickedObject = this.#viewer.scene.pick(e.endPosition);
                  const obj = {
                    entityVal: pickedObject && pickedObject.id ? pickedObject.id : '',
                    x: e.endPosition.x,
                    y: e.endPosition.y,
                    show: false,
                    type: "",
                    content: "",
                  };
                  document.body.style.cursor = "default";
                  if (pickedObject && pickedObject.id) {
                    if (pickedObject.id.name) {
                      const graphic = pickedObject.id.name as any;
                      document.body.style.cursor = "pointer";
                      // 图标不是点位的话，不做弹窗信息展示
                      if (pickedObject.id.name.TYPE !== "POINT") return;
                      obj.show = true;
                      obj.type = pickedObject.id.name.TYPE;
                      if (pickedObject.id.name.TYPE === "POINT") {
                        obj.content = `
                      <p>${graphic.NAME ? `监测点：${graphic.NAME}` : ""
                          }</p>
                      <p><span>坐标： ${graphic.X}， ${graphic.Y
                          }</span></p>
                      <b><span style="float: right;color: lightblue;font-size: 12px;">点击查看更多</span></b>
                  `;
                      }
                    }
                  }
                  callback(obj);
                },
                15
              );
              break;
            case "WHEEL":
              handler.setInputAction((e: number) => {
                callback(e);
              }, 16);
              break;
          }
        };

        console.timeEnd(`Cesium加载耗时:`);
      })
      .catch((e) => {
        message.error(`当前模式为离线模式，请检查网络连接！${e}`, 0);
      });
  }

  get terrainProvider (): Cesium.CesiumTerrainProvider {
    return this.#terrainProvider;
  }
  set terrainProvider (value: Cesium.CesiumTerrainProvider) {
    this.#terrainProvider = value;
  }

  get imageryProvider (): Cesium.ArcGisMapServerImageryProvider | null {
    return this.#imageryProvider;
  }
  set imageryProvider (value: Cesium.ArcGisMapServerImageryProvider | null) {
    this.#imageryProvider = value;
  }

  get measurementLayer (): Cesium.CustomDataSource {
    return this.#measurementLayer;
  }

  get tileset3D (): Cesium.Cesium3DTileset {
    return this.#tileset3D;
  }

  #addKeydownListener () {
    // document.body.addEventListener("keydown", (event: any) => {
    // const key = event.key.toLowerCase();
    // if (key === "w") {
    //   this.#viewer.camera.moveForward(8);
    // } else if (key === "s") {
    //   this.#viewer.camera.moveBackward(8);
    // } else if (key === "a") {
    //   this.#viewer.camera.moveLeft(8);
    // } else if (key === "d") {
    //   this.#viewer.camera.moveRight(8);
    // }
    // });
  }

  #transformWGS84ToCartesian (
    position: { x: number; y: number; z: number } | undefined,
    alt: number
  ) {
    // 坐标转换 84转笛卡尔
    if (this.#viewer) {
      return position
        ? Cesium.Cartesian3.fromDegrees(
          position.x,
          position.y,
          (position.z = alt || position.z),
          Cesium.Ellipsoid.WGS84
        )
        : Cesium.Cartesian3.ZERO;
    }
  }

  transformWGS84ToCartesian (position: { x: number; y: number; z: number } | undefined,
    alt: number) {
    return this.#transformWGS84ToCartesian(position,
      alt)
  }

  #transformCartesianToWGS84 (cartesian: Cesium.Cartesian3) {
    // 坐标转换 笛卡尔转84
    if (this.#viewer && cartesian) {
      const cartographic =
        Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian);
      return {
        x: Cesium.Math.toDegrees(cartographic.longitude),
        y: Cesium.Math.toDegrees(cartographic.latitude),
        z: cartographic.height,
      };
    }
  }
  transformCartesianToWGS84 (cartesian: Cesium.Cartesian3) {
    return this.#transformCartesianToWGS84(cartesian)
  }

  #transformCartesianArrayToWGS84Array (cartesianArr: Cesium.Cartesian2[]) {
    // 坐标数组转换 笛卡尔转86
    if (this.#viewer) {
      return cartesianArr
        ? cartesianArr.map((item: any) => {
          return this.#transformCartesianToWGS84(item);
        })
        : [];
    }
  }

  #transformWGS84ToCartographic (position: Cesium.Cartesian3) {
    // 84坐标转弧度坐标
    return position
      ? Cesium.Cartographic.fromDegrees(position.x, position.y, position.z)
      : Cesium.Cartographic.ZERO;
  }

  #getCatesian3FromPX = (px: Cesium.Cartesian2) => {
    // 拾取位置点
    if (this.#viewer && px) {
      const picks = this.#viewer.scene.drillPick(px);
      let cartesian = null as unknown as Cesium.Cartesian3 | undefined;
      let isOn3dtiles = false;
      let isOnTerrain = false;

      for (let i in picks) {
        const pick = picks[i];

        if (
          (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
          (pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
          (pick && pick.primitive instanceof Cesium.Model)
        ) {
          //模型上拾取
          isOn3dtiles = true;
        }

        if (isOn3dtiles) {
          this.#viewer.scene.pick(px); // pick
          // console.log(this.#viewer.scene)
          cartesian = this.#viewer.scene.pickPosition(px);
          if (cartesian) {
            const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
            if (cartographic.height < 0) cartographic.height = 0;
            const lon = Cesium.Math.toDegrees(cartographic.longitude) as number;
            const lat = Cesium.Math.toDegrees(cartographic.latitude) as number;
            const height = cartographic.height as number;
            cartesian = this.#transformWGS84ToCartesian(
              { x: lon, y: lat, z: height },
              height
            );
          }
        }
      }
      // 地形
      let boolTerrain =
        this.#viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;

      if (!isOn3dtiles && !boolTerrain) {
        const ray = this.#viewer.scene.camera.getPickRay(px);
        if (!ray) return null;
        cartesian = this.#viewer.scene.globe.pick(ray, this.#viewer.scene);
        isOnTerrain = true;
      }
      // 地球
      if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
        cartesian = this.#viewer.scene.camera.pickEllipsoid(
          px,
          this.#viewer.scene.globe.ellipsoid
        );
      }
      if (cartesian) {
        const position = this.#transformCartesianToWGS84(cartesian);
        if (position?.z && position?.z < 0) {
          cartesian = this.#transformWGS84ToCartesian(position, 0.1);
        }
        return cartesian;
      }
      return false;
    }
  };
  getCatesian3PX (px: Cesium.Cartesian2) {
    return this.#getCatesian3FromPX(px);
  }

  #getPositionDistance (positions: Cesium.Cartesian3[]) {
    // 获取84坐标的距离
    let distance = 0;
    for (let i = 0; i < positions.length - 1; i++) {
      let point1cartographic = this.#transformWGS84ToCartographic(positions[i]);
      let point2cartographic = this.#transformWGS84ToCartographic(
        positions[i + 1]
      );
      let geodesic = new Cesium.EllipsoidGeodesic();
      geodesic.setEndPoints(point1cartographic, point2cartographic);
      let s = geodesic.surfaceDistance;
      s = Math.sqrt(
        Math.pow(s, 2) +
        Math.pow(point2cartographic.height - point1cartographic.height, 2)
      );
      distance = distance + s;
    }
    return distance.toFixed(2);
  }

  #getPositionsArea (positions: Cesium.Cartesian3[]) {
    // 计算一组坐标组成多边形的面积
    let result = "";
    if (positions) {
      let h = 0;
      const ellipsoid = Cesium.Ellipsoid.WGS84;
      positions.push(positions[0]);
      for (let i = 1; i < positions.length; i++) {
        const oel = ellipsoid.cartographicToCartesian(
          this.#transformWGS84ToCartographic(positions[i - 1])
        );
        const el = ellipsoid.cartographicToCartesian(
          this.#transformWGS84ToCartographic(positions[i])
        );
        h += oel.x * el.y - el.x * oel.y;
      }
      result = (Math.abs(h) / 100).toFixed(2);
    }
    return result;
  }

  // 提示标签
  #addInfoPoint (position: Cesium.Cartesian2, calculateId: string, text: string, isClose = false) {
    const labelEntity = new Cesium.Entity() as any;
    labelEntity.position = position;
    if (isClose == true) {
      labelEntity.name = { TYPE: 'CLEAR', calculateId };
      labelEntity.billboard = {
        image: './iconImg/closeIcon.png', // 默认图标
        // scale: 0.3, // 图标缩放比例
        width: 30,
        height: 30,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 将广告牌底部与位置对齐
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        eyeOffset: new Cesium.Cartesian3(-3.0, 0.0, 0.0),
        disableDepthTestDistance: Number.POSITIVE_INFINITY, // 漂移bug Number.POSITIVE_INFINITY
        scaleByDistance: new Cesium.NearFarScalar(1e2, 1.5, 5e3, 0.0),
      };
    } else {
      labelEntity.point = {
        pixelSize: 10,
        outlineColor: Cesium.Color.BLUE,
        outlineWidth: 5,
      };
      labelEntity.label = {
        text,
        show: true,
        showBackground: true,
        font: "24px monospace",
        horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(0, 0), // 调整文字位置
        disableDepthTestDistance: Number.POSITIVE_INFINITY, // 漂移bug Number.POSITIVE_INFINITY
        scaleByDistance: new Cesium.NearFarScalar(1e2, 1.5, 5e3, 0.0)
      };
    }
    let pointObj = this.#measurementLayer.entities.add(labelEntity);
    if (!(this.#calculateInfo[calculateId] instanceof Array)) this.#calculateInfo[calculateId] = [];
    // console.log(this.#calculateInfo)
    this.#calculateInfo[calculateId].push(pointObj)
  }
}
